package com.zzy.study.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.*;

/**
 * @ClassName DBUtil
 * @Description ToDo
 * @Auther teacher Bai
 * @Date 2021/2/20 10:36
 */
public class DBUtil {
    // http://IP  : 端口号
    public static String URL ;
    public static String USERNAME ;
    public static String PASSWORD ;
    public static String DRIVER ;

    /**
     * 加载驱动
     */
    static {
        try {
            InputStream stream = DBUtil.class.getResourceAsStream("/db.properties");
            //System.out.println(stream);
            Properties p = new Properties();
            p.load(stream);
            DRIVER = (String)p.get("driver");
            URL = (String) p.get("url");
            USERNAME = (String) p.get("user");
            PASSWORD = (String) p.get("password");
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法的三要素：
     *      返回值类型
     *      方法名
     *      参数列表
     */
    /**
     * 获取连接对象
     * @return
     */
    public static Connection getConn(){
        try {
            return DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    /**
     * 获取List<List>类型的数据格式</>
     * @param sql
     * @param objs
     * Object... 表示可变参数
     * @return
     */
    public static List<List> queryList(String sql,Object... objs){
        //获取连接
        Connection conn = getConn();
        PreparedStatement ps = null;
        //创建一个大的List用来转储 数据表中所有的数据
        ArrayList<List> lists = new ArrayList<>();
        ResultSet set = null;
        try {
            //获取预编译对象
            ps = conn.prepareStatement(sql);
            //设置参数
            setParm(ps,objs);
            //执行sql语句  得到ResultSet 结果集
            set = ps.executeQuery();
            while (set.next()){
                //创建一个小的List用来转储 数据表中的每一行数据
                ArrayList<Object> list = new ArrayList<>();
                for(int i=0;i<set.getMetaData().getColumnCount();i++){
                    list.add(set.getObject(i + 1));
                }
                lists.add(list);
            }
            return lists;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(set,ps,conn);
        }
        return null;
    }

    /**
     * 获取封装List<Map>格式的数据</>
     * @param sql
     * @param objs
     * @return
     */
    public static List<Map> queryListMap(String sql, Object... objs){
        //获取连接
        Connection conn = getConn();
        PreparedStatement ps = null;
        //创建一个大的List用来转储 数据表中所有的数据
        ArrayList<Map> lists = new ArrayList<>();
        ResultSet set = null;
        try {
            //获取预编译对象
            ps = conn.prepareStatement(sql);
            //设置参数
            setParm(ps,objs);
            //执行sql语句  得到ResultSet 结果集
            set = ps.executeQuery();
            while (set.next()){
                //创建一个小的map用来转储 数据表中的每一行数据
                HashMap<Object, Object> map = new HashMap<>();
                for(int i=0;i<set.getMetaData().getColumnCount();i++){
                    map.put(set.getMetaData().getColumnName(i+1),set.getObject(i+1));
                }
                lists.add(map);
            }
            return lists;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(set,ps,conn);
        }
        return null;
    }

    /**
     * 封装通用的增删改方法
     * @param sql
     * @param objs
     * @return
     */
    public static int update(String sql, Object... objs){
        Connection conn = getConn();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            setParm(ps,objs);
            return ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(null,ps,conn);
        }
        return -1;
    }

    /**
     * 封装通用的关闭方法
     * @param set
     * @param ps
     * @param conn
     */
    public static void closeAll(ResultSet set, PreparedStatement ps,Connection conn){
        try{
            if(set!=null){
                set.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        try{
            if(ps!=null){
                ps.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        try{
            if(conn!=null){
                conn.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 封装设置参数的方法
     * @param ps
     * @param objs
     */
    public static void setParm(PreparedStatement ps,Object... objs){
        //向sql语句中设置参数
        if(objs.length>0){
            for(int i=0;i< objs.length;i++){
                try {
                    ps.setObject(i+1,objs[i]);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取新增操作执行的 行的 主键id
     * @param sql
     * @param objs
     * @return
     */
    public static int getPrimaryKey(String sql, Object... objs){
        Connection conn = getConn();
        PreparedStatement ps = null;
        ResultSet keys = null;
        try {
            //如果获取主键需要再预编译对象时  加一个参数 Statement.RETURN_GENERATED_KEYS
            ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            setParm(ps,objs);
            ps.executeUpdate();//执行sql 语句
            //ps.getGeneratedKeys() 获取生成的主键id
            keys = ps.getGeneratedKeys();
            if(keys.next()){
                return keys.getInt(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(keys,ps,conn);
        }
        return -1;
    }
}
